#include "TimedComandConfigPage.h"
#include "TimedLoopCommandManager.h"
#include "MachineDependents.h"
#include "StringListEditor.h"
#include "LoopStatus.h"
#include "LoopScheduler.h"
#include "SystemStatus.h"
#include "Button.h"


const StringVectorPtr TimedComandConfigPage::fourOrFive{new StringVector{"4", "5"}};


TimedComandConfigPage::TimedComandConfigPage(const int pageNum) : super(pageNum), mtimedLoopCommandManager(TimedLoopCommandManagerSingleton::instance()) {
    mpageSize = 1;
}


TimedComandConfigPage::~TimedComandConfigPage() {
    //dtor
}



void TimedComandConfigPage::paint() {
    if (focus) {
        super::paint();
    } else {
        std::string_view statusView = static_cast <std::string_view>(*mploopControlInfo);
        const LoopSize_t length = std::min(mploopControlInfo->length, static_cast <LoopSize_t>(Screen::SCREEN_WIDTH));
        if (0 == mmultiPageNo) {
            resetStream();
            strStream << "timedCommand " << std::setw(3) << pageNum;
            std::string first = strStream.str();

            resetStream();
            strStream << "begin:" << std::setw(10) << std::put_time(&mbeginTime,"%T");
            std::string second = strStream.str();

            resetStream();
            strStream << "end  :" <<std::setw(10) << std::put_time(&mendTime,"%T");
            std::string third = strStream.str();

            resetStream();
            //    std::string four(reinterpret_cast <std::string::const_pointer>(mploopControlInfo->loopStatus, mploopControlInfo->length));
            std::string four(statusView.substr(0, length));
            screen.show(&first, &second, &third, &four);
        } else {
            std::string fullScreen(statusView.substr(length));

            fullScreen.resize(Screen::SCREEN_WIDTH * Screen::SCREEN_HEIGHT - DELETE_STR.size(), ' ');
            fullScreen += DELETE_STR;
            screen.showFast(0, 0, Screen::SCREEN_WIDTH, Screen::SCREEN_HEIGHT, fullScreen);
        }
    }
}


void TimedComandConfigPage::initEditors() {
    StringListEditor* pStringEditor = nullptr;

    mscrollEditors.clear();
    mscrollEditors.resize(mpageSize);
    const LoopSize_t length = std::min(static_cast <LoopSize_t>(Screen::SCREEN_WIDTH), mploopControlInfo->length);
    {
        BasicEditorVector& editorVector = mscrollEditors.at(0);
        IntEditor* pEditor = new IntEditor(1, 6, 7, 0, 23, 1);//HOUR
        pEditor->format = "%02d";
        editorVector.push_back(BasicEditorSharedPtr(pEditor));

        pEditor = new IntEditor(1, 9, 10, 0, 59, 1);//MINUTE
        pEditor->format = "%02d";
        editorVector.push_back(BasicEditorSharedPtr(pEditor));

        pEditor = new IntEditor(1, 12, 13, 0, 59, 1);//SECOND
        pEditor->format = "%02d";
        editorVector.push_back(BasicEditorSharedPtr(pEditor));


        pEditor = new IntEditor(2, 6, 7, 0, 23, 1);//HOUR
        pEditor->format = "%02d";
        editorVector.push_back(BasicEditorSharedPtr(pEditor));

        pEditor = new IntEditor(2, 9, 10, 0, 59, 1);//MINUTE
        pEditor->format = "%02d";
        editorVector.push_back(BasicEditorSharedPtr(pEditor));

        pEditor = new IntEditor(2, 12, 13, 0, 59, 1);//SECOND
        pEditor->format = "%02d";
        editorVector.push_back(BasicEditorSharedPtr(pEditor));

        const LoopStatus* ploopStatus = mploopControlInfo->loopStatus;
        for (LoopSize_t i = 0; i < length; ++i) {
            pStringEditor = new StringListEditor(3, i, i, fourOrFive);
            editorVector.push_back(BasicEditorSharedPtr(pStringEditor));
        }
    }
    {
        BasicEditorVector& editorVector = mscrollEditors.at(1);
        LoopSize_t row, colunm;
        const LoopSize_t remainLength = mploopControlInfo->length - length;
        for (LoopSize_t i = 0; i < remainLength; ++i) {
            row = i / Screen::SCREEN_WIDTH;
            colunm = i % Screen::SCREEN_WIDTH;
            pStringEditor = new StringListEditor(row, colunm, colunm, fourOrFive);
            editorVector.push_back(BasicEditorSharedPtr(pStringEditor));
        }

        Button* pbutton = new Button(3, 10, 15, DELETE_STR, this, 1);
        editorVector.push_back(BasicEditorSharedPtr(pbutton));
    }
}



void TimedComandConfigPage::beforeDisplay() {

    mploopControlInfo = mtimedLoopCommandManager.load(DateTimeUtility::ClockTime_t::zero());
    if (!mploopControlInfo) {
        TimedLoopCommandManager::getDefaultTimedInfo(mploopControlInfo);
    } else {
        mploopControlInfo.reset(new(mploopControlInfo->length) LoopControlInfo(*mploopControlInfo), LoopControlInfo::releaseMemory);
    }

    mbeginTime = DateTimeUtility::toTm(DateTimeUtility::toTime_t(mploopControlInfo->beginTime));
    mendTime = DateTimeUtility::toTm(DateTimeUtility::toTime_t(mploopControlInfo->beginTime + mploopControlInfo->duration));

//    mpageSize = (mploopControlInfo->length + 111) / 64;

    mpageSize = 2;

//    LOG_DEDUG("mpageSize:%d", mpageSize);
    super::beforeDisplay();
}



/**
 * 为可编辑单元设置初始值
 * 需要在进入编辑模式 和 初始化的时候调用
 */
void TimedComandConfigPage::setValue() {
    StringListEditor* pStringEditor = nullptr;
    const LoopSize_t length = std::min(static_cast <LoopSize_t>(Screen::SCREEN_WIDTH), mploopControlInfo->length);
    const LoopStatus* ploopStatus = mploopControlInfo->loopStatus;

    {
        BasicEditorVector& editorVector = mscrollEditors.at(0);
        std::tm nowTm = DateTimeUtility::getTime();

        static_cast<IntEditor*> (editorVector[0].get())->setValue(mbeginTime.tm_hour);
        static_cast<IntEditor*> (editorVector[1].get())->setValue(mbeginTime.tm_min);
        static_cast<IntEditor*> (editorVector[2].get())->setValue(mbeginTime.tm_sec);

        static_cast<IntEditor*> (editorVector[3].get())->setValue(mendTime.tm_hour);
        static_cast<IntEditor*> (editorVector[4].get())->setValue(mendTime.tm_min);
        static_cast<IntEditor*> (editorVector[5].get())->setValue(mendTime.tm_sec);

        for (LoopSize_t i = 0; i < length; ++i) {
            pStringEditor = static_cast<StringListEditor*> (editorVector[6 + i].get());
            pStringEditor->setValue(ploopStatus[i] - LoopStatus::TIMER_OFF);
        }
    }  {
        BasicEditorVector& editorVector = mscrollEditors.at(1);
        for (LoopSize_t i = length; i < mploopControlInfo->length; ++i) {
            pStringEditor = static_cast<StringListEditor*> (editorVector[i - length].get());
            pStringEditor->setValue(ploopStatus[i] - LoopStatus::TIMER_OFF);
        }
    }

}



/**
 * 设置时间数据
 */
void TimedComandConfigPage::saveValue() {
    std::tm nowTm = DateTimeUtility::getTime();
    StringListEditor* pStringEditor = nullptr;
    LoopStatus* ploopStatus = nullptr;
    const LoopSize_t length = std::min(static_cast <LoopSize_t>(Screen::SCREEN_WIDTH), mploopControlInfo->length);
    {
        BasicEditorVector& editorVector = mscrollEditors.at(0);
        mbeginTime.tm_sec = static_cast<IntEditor*> (editorVector[2].get())->getValue();
        mbeginTime.tm_min = static_cast<IntEditor*> (editorVector[1].get())->getValue();
        mbeginTime.tm_hour = static_cast<IntEditor*> (editorVector[0].get())->getValue();

        mendTime.tm_sec = static_cast<IntEditor*> (editorVector[5].get())->getValue();
        mendTime.tm_min = static_cast<IntEditor*> (editorVector[4].get())->getValue();
        mendTime.tm_hour = static_cast<IntEditor*> (editorVector[3].get())->getValue();

        mploopControlInfo->beginTime = DateTimeUtility::to_ClockTime(::mktime(&mbeginTime));
        DateTimeUtility::ClockTime_t endTime = DateTimeUtility::to_ClockTime(::mktime(&mendTime));
//    if (endTime <= mploopControlInfo->beginTime) {
//        endTime += DateTimeUtility::TICK_COUNT_OF_DAY;
//    }

        DateTimeUtility::ClockTime_t duration = (endTime - mploopControlInfo->beginTime) % DateTimeUtility::TICK_COUNT_OF_DAY;
        if (DateTimeUtility::ClockTime_t::zero() >= duration) {
            duration += DateTimeUtility::TICK_COUNT_OF_DAY;
        } else if (DateTimeUtility::TICK_COUNT_OF_DAY < duration) {
            duration %= DateTimeUtility::TICK_COUNT_OF_DAY;
        }


        mploopControlInfo->duration = duration;//endTime - mploopControlInfo->beginTime
        mploopControlInfo->commandType = LoopCommandType::TIMED_COMMAND;
        ploopStatus = mploopControlInfo->loopStatus;
        for (LoopSize_t i = 0; i < length; ++i) {
            pStringEditor = static_cast<StringListEditor*> (editorVector[6 + i].get());
            ploopStatus[i] = static_cast <LoopStatus>(pStringEditor->getText()[0]);
        }
    } {
        BasicEditorVector& editorVector = mscrollEditors.at(1);
        for (LoopSize_t i = length; i < mploopControlInfo->length; ++i) {
            pStringEditor = static_cast<StringListEditor*> (editorVector[i - length].get());
            ploopStatus[i] = static_cast <LoopStatus>(pStringEditor->getText()[0]);
        }
    }

    LoopScheduler& loopScheduler = LoopSchedulerSingleton::instance();
//    LOG_DEDUG("begin save timed info");
    if (SystemStatus::OFFLINE == loopScheduler.msystemStatus) {
        loopScheduler.clear();
        mtimedLoopCommandManager.save(mploopControlInfo);

        loopScheduler.offline(nullptr);
    } else {
        mtimedLoopCommandManager.save(mploopControlInfo);

    }
//    LOG_DEDUG("end save timed info");
}



int TimedComandConfigPage::onClick(const uint16_t id, Button* const pbutton) {
    LoopScheduler& loopScheduler = LoopSchedulerSingleton::instance();
    if (SystemStatus::OFFLINE == loopScheduler.msystemStatus) {
        loopScheduler.clear();
        mtimedLoopCommandManager.clear();

        loopScheduler.offline(nullptr);
    } else {
        mtimedLoopCommandManager.clear();
    }

    super::cancelEdit();
    afterDisplay();
    beforeDisplay();
    paint();

    return 1;
}
